package com.yeyks.util;

import com.aliyun.oss.common.utils.DateUtil;
import com.yeyks.base.Arguments;
import com.google.common.collect.Maps;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
import java.util.Date;
import java.util.Map;

/**
 * @author fuchangshuai
 * @time 2018/12/26
 */
public class DateUtils {
    public static final Integer DATE_TYPE_DAY = 1;  //今日
    public static final Integer DATE_TYPE_YESTERDAY = 2;  //昨天
    public static final Integer DATE_TYPE_WEEK = 3; //本周
    public static final Integer DATE_TYPE_LASTWEEK = 4; //上周
    public static final Integer DATE_TYPE_MONTH = 5; //本月
    public static final Integer DATE_TYPE_LASTMONTH = 6; //上月
    static public DateTimeFormatter yyyyMMddHHmmssformatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    static public DateTimeFormatter yyyyMMddHHmmformatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
    static public DateTimeFormatter yyyyMMddformatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    static public DateTimeFormatter hhmmformatter = DateTimeFormatter.ofPattern("HH:mm");

    /**
     * 0 全部，1 今日，2 昨日，3 本周，4 上周，5 本月 6上月
     *
     * @param type
     * @return
     */
    public static Map<String, Object> constructParamMapByTimeRangeType(int type) {
        Map<String, Object> params = Maps.newHashMap();
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime startOfToday = now.toLocalDate().atStartOfDay();
        int dayOfThisWeek = startOfToday.getDayOfWeek().getValue();
        LocalDateTime startOfThisWeek = startOfToday.minusDays(dayOfThisWeek - 1);
        LocalDate today = LocalDate.now();
        int dayOfThisMonth = today.getDayOfMonth();
        LocalDateTime startOfThisMonth = startOfToday.minusDays(dayOfThisMonth - 1);
        switch (type) {
            case 1:
                params.put("startTime", toDate(startOfToday));
                params.put("endTime", toDate(now));
                break;
            case 2:
                LocalDateTime startOfYestoday = startOfToday.minusDays(1);
                params.put("startTime", toDate(startOfYestoday));
                params.put("endTime", toDate(startOfToday));
                break;
            case 3:
                params.put("startTime", toDate(startOfThisWeek));
                params.put("endTime", toDate(now));
                break;
            case 4:
                LocalDateTime startOfLastWeek = startOfThisWeek.minusWeeks(1);
                params.put("startTime", toDate(startOfLastWeek));
                params.put("endTime", toDate(startOfThisWeek));
                break;
            case 5:
                params.put("startTime", toDate(startOfThisMonth));
                params.put("endTime", toDate(now));
                break;
            case 6:
                LocalDateTime startOfLastMonth = startOfThisMonth.minusMonths(1);
                params.put("startTime", toDate(startOfLastMonth));
                params.put("endTime", toDate(startOfThisMonth));
                break;
        }
        return params;
    }


    /**
     * 0 全部，1 今日，2 昨日，3 本周，4 上周，5 本月 6上月
     *
     * @param type
     * @return
     */
    public static TimeRangeDO getTimeRange(int type) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime startOfToday = now.toLocalDate().atStartOfDay();
        int dayOfThisWeek = startOfToday.getDayOfWeek().getValue();
        LocalDateTime startOfThisWeek = startOfToday.minusDays(dayOfThisWeek - 1);
        LocalDate today = LocalDate.now();
        int dayOfThisMonth = today.getDayOfMonth();
        LocalDateTime startOfThisMonth = startOfToday.minusDays(dayOfThisMonth - 1);
        TimeRangeDO rangeDO = new TimeRangeDO();
        switch (type) {
            case 1:
                rangeDO.setStartOfTime(startOfToday);
                rangeDO.setEndOfTime(now);
                break;
            case 2:
                LocalDateTime startOfYestoday = startOfToday.minusDays(1);
                rangeDO.setStartOfTime(startOfYestoday);
                rangeDO.setEndOfTime(startOfToday);
                break;
            case 3:
                rangeDO.setStartOfTime(startOfThisWeek);
                rangeDO.setEndOfTime(now);
                break;
            case 4:
                LocalDateTime startOfLastWeek = startOfThisWeek.minusWeeks(1);
                rangeDO.setStartOfTime(startOfLastWeek);
                rangeDO.setEndOfTime(startOfThisWeek);
                break;
            case 5:
                rangeDO.setStartOfTime(startOfThisMonth);
                rangeDO.setEndOfTime(now);
                break;
            case 6:
                LocalDateTime startOfLastMonth = startOfThisMonth.minusMonths(1);
                rangeDO.setStartOfTime(startOfLastMonth);
                rangeDO.setEndOfTime(startOfThisMonth);
                break;
        }
        return rangeDO;
    }


    /**
     * 根据指定的类型获取时间区间
     *
     * @param localDateTime
     * @param type          1表示当天起始，3表示当周起始 5月
     * @return
     */
    public static TimeRangeDO getTimeRange(LocalDateTime localDateTime, int type) {
        LocalDateTime startOfToday = localDateTime.toLocalDate().atStartOfDay();
        int dayOfThisWeek = startOfToday.getDayOfWeek().getValue();
        LocalDateTime startOfThisWeek = startOfToday.minusDays(dayOfThisWeek - 1);
        TimeRangeDO result = new TimeRangeDO();
        if (type == DATE_TYPE_DAY) {
            result.setStartOfTime(startOfToday);
            result.setEndOfTime(startOfToday.plusDays(1).minusSeconds(1));
        } else if (type == DATE_TYPE_WEEK) {
            result.setStartOfTime(startOfThisWeek);
            result.setEndOfTime(startOfThisWeek.plusDays(7).minusSeconds(1));
        }
        return result;
    }

    /**
     * localDateTime转Date类型
     *
     * @param localDateTime
     * @return
     */
    private static Date toDate(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * localDate转Date类型
     *
     * @param localDate
     * @return
     */
    public static Date localDateToDate(LocalDate localDate) {
        return Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
    }


    /**
     * date 转换成 LocalDateTime
     *
     * @param date
     * @return
     */
    public static LocalDateTime toLocalDateTime(Date date) {
        return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
    }

    /**
     * date 转换成 LocalDate
     *
     * @param date
     * @return
     */
    public static LocalDate toLocalDate(Date date) {
        return toLocalDateTime(date).toLocalDate();
    }

    /**
     * 将 yyyy-MM-dd 类型的转化日期格式
     *
     * @param dateStr
     * @return 日期
     */
    public static Date yyyyMMddToDate(String dateStr) {
        if (!Arguments.notEmpty(dateStr)) {
            return null;
        }
        LocalDate date = LocalDate.parse(dateStr);
        return DateUtils.localDateToDate(date);
    }

    /**
     * 将时间戳转换成yyyy-MM-dd格式的date类型
     *
     * @param dateStr
     * @return 日期
     */
    public static Date stampToDate(Long dateStr) {
        if (dateStr == null || dateStr == 0) {
            return null;
        }
        Date stampDate = new Date(dateStr);
        LocalDate date = toLocalDate(stampDate);
        return DateUtils.localDateToDate(date);
    }

    /**
     * 将时间戳转换成yyyy-MM-dd格式
     *
     * @param dateStr
     * @return 日期
     */
    public static String stampToYYYYMMDD(Long dateStr) {
        if (dateStr == null || dateStr == 0) {
            return null;
        }
        LocalDateTime localDateTime = DateUtils.toLocalDateTime(new Date(dateStr));
        String s = DateUtils.formatDate(localDateTime);
        return DateUtils.formatDate(localDateTime);
    }

    /**
     * 将 yyyy-MM-dd HH:mm:ss 类型的转化日期格式
     *
     * @param dateStr
     * @return 日期
     */
    public static Date toDateTime(String dateStr) {
        if (!Arguments.notEmpty(dateStr)) {
            return null;
        }
        LocalDateTime time = parseLocalDateTime(dateStr);
        return time == null ? null : DateUtils.toDate(time);
    }

    /**
     * 获取两个日期之间相差的天数
     *
     * @param begin
     * @param end
     * @return
     */
    public static Long getDayByBeginEnd(Date begin, Date end) {
        LocalDate beginLocalDate = toLocalDate(begin);
        LocalDate endLocalDate = toLocalDate(end);

        return endLocalDate.toEpochDay() - beginLocalDate.toEpochDay();
    }

    public static String format(TemporalAccessor dateTime, String format) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
        return formatter.format(dateTime);
    }

    public static String format(LocalDateTime dateTime) {
        return format(dateTime, yyyyMMddHHmmssformatter);
    }

    public static String format(LocalDateTime dateTime, DateTimeFormatter formatter) {
        if (dateTime == null) {
            return null;
        }
        return formatter.format(dateTime);
    }

    public static String format(Date date) {
        if (date == null) {
            return null;
        }
        return format(toLocalDateTime(date));
    }

    public static String format(Date date, DateTimeFormatter formatter) {
        if (date == null) {
            return null;
        }
        return format(toLocalDateTime(date), formatter);
    }

    public static String toYYMMddStr(Date date) {
        if (date == null) {
            return null;
        }
        return formatDate(toLocalDateTime(date));
    }

    public static String formatDate(LocalDateTime dateTime) {
        return yyyyMMddformatter.format(dateTime);
    }

    public static Date parserDate(String format) {
        LocalDateTime localDateTime = parseLocalDateTime(format);
        return localDateTime == null ? null : DateUtils.toDate(localDateTime);
    }

    public static LocalDateTime parseLocalDateTime(String format) {
        if (!Arguments.notEmpty(format)) {
            return null;
        }
        return LocalDateTime.parse(format, yyyyMMddHHmmssformatter);
    }

    public static LocalDateTime changeLocalDateTime(String format) {
        if (!Arguments.notEmpty(format)) {
            return null;
        }
        return LocalDateTime.parse(format, yyyyMMddHHmmformatter);
    }

    public static LocalDateTime parseLocalDateTime(String format, String yyyyMMddHHmmss) {
        if (!Arguments.notEmpty(format)) {
            return null;
        }

        DateTimeFormatter yyyyMMddHHmmssformatter = DateTimeFormatter.ofPattern(yyyyMMddHHmmss);
        return LocalDateTime.parse(format, yyyyMMddHHmmssformatter);
    }

    public static LocalDate parseLocalDate(String format) {
        return LocalDate.parse(format);
    }

    public static LocalTime parseLocalTime(String format) {
        return LocalTime.parse(format, hhmmformatter);
    }

    public static Integer getDaysBetween(LocalDateTime startTime, LocalDateTime endTime) {
        if (!endTime.isAfter(startTime)) {
            return 0;
        }
        Integer startDay = startTime.getDayOfYear();
        Integer startYear = startTime.getYear();
        Integer endDay = endTime.getDayOfYear();
        Integer endYear = endTime.getYear();

        //先不管闰年 366情况
        return (endYear - startYear) * 365 + endDay - startDay + 1;

    }

    /**
     * 获取当前时间的分钟数
     *
     * @return 分钟
     */
    public static Integer getCurrentMinuteOfDay() {
        LocalDateTime now = LocalDateTime.now();
        return now.getHour() * 60 + now.getMinute();
    }

    public static Boolean isToday(LocalDateTime time) {
        if (time == null) {
            return false;
        }
        LocalDate date = LocalDate.now();
        return date.isEqual(time.toLocalDate());
    }

    public static Boolean isToday(Date date) {
        if (date == null) {
            return false;
        }
        LocalDate today = LocalDate.now();
        return today.isEqual(toLocalDate(date));
    }

    public static Boolean isYesterday(Date date) {
        if (date == null) {
            return false;
        }
        LocalDate today = LocalDate.now().minusDays(1);
        return today.isEqual(toLocalDate(date));
    }

    public static Date dayBefore(Date date, Integer number) {
        return toDate(DateUtils.toLocalDateTime(date).plusDays(number));
    }

    /**
     * 对应当前n天前时间(0代表当前时间，1...表前n天，-1...表后n天)
     *
     * @param number
     * @return date
     */
    public static Date dayBefore(Integer number) {
        return toDate(LocalDateTime.now().minusDays(number));
    }

    public static String dayBefores(Integer number) {
        return format(dayBefore(number));
    }

    /**
     * 获取当天开始时间（0表示当前,-1...表前n天，1...表后n天）
     *
     * @param day
     * @return
     */
    public static Date dayBegin(Integer day) {
        return toDate(LocalDateTime.of(LocalDate.now().plusDays(day), LocalTime.MIN));
    }

    /**
     * 获取距离date开始时间（0表示当前,-1...表前n天，1...表后n天）
     *
     * @param day
     * @param date
     * @return
     */
    public static Date dayBegin(Date date, Integer day) {
        LocalDate localDate = DateUtils.toLocalDate(date);
        return toDate(LocalDateTime.of(localDate.plusDays(day), LocalTime.MIN));
    }

    public static String dayBegins(Integer day) {
        return format(dayBegin(day));
    }

    /**
     * 获取当天结束时间（0表示当前,-1...表前n天，1...表后n天）
     *
     * @param day
     * @return
     */
    public static Date dayEnd(Integer day) {
        return toDate(LocalDateTime.of(LocalDate.now().plusDays(day), LocalTime.MAX));
    }

    public static String dayEnds(Integer day) {
        return format(dayEnd(day));
    }

    /**
     * 获取昨天凌晨后n小时的时间
     *
     * @param hours
     * @return
     */
    public static Date yesterdayAfterHour(Integer hours) {
        return toDate(LocalDateTime.of(LocalDate.now().minusDays(1), LocalTime.MIN).plusHours(hours));
    }

    public static String yesterdayAfterHours(Integer hours) {
        return format(yesterdayAfterHour(hours));
    }

    /**
     * 获取据现在后几分钟的时间
     *
     * @param minutes
     * @return date
     */
    public static Date nowAfterMinuteToDate(Integer minutes) {
        return toDate(LocalDateTime.now().plusMinutes(minutes));
    }

    /**
     * 获取据现在后几分钟的时间
     *
     * @param minutes
     * @return string
     */
    public static String nowAfterMinutesToStr(Integer minutes) {
        return format(nowAfterMinuteToDate(minutes));
    }

    /**
     * 获取据date后几分钟的时间
     *
     * @param minutes
     * @return date
     */
    public static Date dateAfterMinute(Date date, Integer minutes) {
        LocalDateTime localDateTime = DateUtils.toLocalDateTime(date);
        return toDate(localDateTime.plusMinutes(minutes));
    }


    /**
     * 根据指定的String类型转换成n小时后的date类型
     *
     * @return date
     */
    public static Date StrAfterHoursToDate(String time, Long hoursNum) {
        if (!Arguments.notEmpty(time)) {
            return null;
        }
        LocalDateTime localDateTime = DateUtils.parseLocalDateTime(time);
        if (localDateTime == null) {
            return null;
        }
        return toDate(localDateTime.plusHours(hoursNum));
    }

    /**
     * 判断据date后hoursNum小时的时间
     *
     * @param date
     * @param hoursNum
     * @return date
     */
    public static Date afterHoursToDate(Date date, Long hoursNum) {
        LocalDateTime localDateTime = DateUtils.toLocalDateTime(date);
        return toDate(localDateTime.plusHours(hoursNum));
    }

    /**
     * 判断据date后dayNum天的时间
     *
     * @param date
     * @param dayNum
     * @return date
     */
    public static Date afterDaysToDate(Date date, Long dayNum) {
        LocalDateTime localDateTime = DateUtils.toLocalDateTime(date);
        return toDate(localDateTime.plusDays(dayNum));
    }

    /**
     * 判断据date后hoursNum小时的时间
     *
     * @param date
     * @param hoursNum
     * @return string
     */
    public static String afterHoursToString(Date date, Long hoursNum) {
        return format(afterHoursToDate(date, hoursNum));
    }

    /**
     * 判断当前时间的小时是否大于hour
     *
     * @return
     */
    public static Boolean afterHour(Integer hour) {
        return LocalDateTime.now().getHour() >= hour;
    }

    /**
     * 获取当前的小时数
     *
     * @return
     */
    public static Integer getNowHour() {
        return LocalDateTime.now().getHour();
    }

    /**
     * 比较dateOne是否大于dateTwo
     *
     * @return
     */
    public static Boolean dateCompareDate(Date dateOne, Date dateTwo) {
        return dateOne.compareTo(dateTwo) >= 0;
    }

    /**
     * 将时间戳转换为时间
     */
    public static String stampToDate(String time) {
        String res;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        long lt = new Long(time);
        Date date = new Date(lt);
        res = simpleDateFormat.format(date);
        return res;
    }

    public static Date stampToDates(String time) {
        return parserDate(stampToDate(time));
    }

    public static Date format2Minute(Date date) {
        String format = format(date, yyyyMMddHHmmformatter);
        if (!Arguments.notEmpty(format)) {
            return null;
        }
        LocalDateTime localDateTime = LocalDateTime.parse(format, yyyyMMddHHmmformatter);

        return toDate(localDateTime);
    }

//    public static void main(String[] args) {
//        LocalDate now = LocalDate.now().plusDays(1);
//        Date date = DateUtils.localDateToDate(now);
//        long l = date.getTime();
//        System.out.println(l);
//    }


}
